#include "EpollPoller.h"
// #include "EpollPoller.h"
// #include "log.h"
// #include "Channel.h"

// #include <errno.h>
// #include <unistd.h>
// #include <strings.h>

// // channel未添加到poller中
// const int kNew = -1;  // channel的成员index_ = -1
// // channel已添加到poller中
// const int kAdded = 1;
// // channel从poller中删除
// const int kDeleted = 2;
EpollPoller::EpollPoller(EventLoop *loop) : Poller(loop), epollfd_(::epoll_create1(EPOLL_CLOEXEC)), events_(KInitEventListSize_)
{
    if (epollfd_ < 0)
    {
        LOG_FATAL("epoll create error code%d \n", errno);
    }
};
EpollPoller::~EpollPoller()
{
    ::close(epollfd_);
}
// 输出型参数输出活跃事件。
TimeStamp EpollPoller::poll(int timeoutMs, ChannelList *activeChannels)
{
    LOG_INFO("fun:%s,=>fd total count:%d\n", __FUNCTION__, channels_.size());
    int numEvents = ::epoll_wait(epollfd_, &*(events_.begin()), static_cast<int>(events_.size()), timeoutMs);
    int saveErrno = errno;
    TimeStamp now(TimeStamp::now());
    if (numEvents > 0)
    {
        LOG_INFO("%d events happend\n", numEvents);
        fillActiveChannel(numEvents, activeChannels);
        if (numEvents == events_.size())
        {
            events_.resize(2 * events_.size());
        }
    }
    else if (numEvents == 0)
    {
        LOG_DEBUGER("%s timeout ! \n", __FUNCTION__);
    }
    else
    {
        if (saveErrno != EINTR)
        {
            errno = saveErrno;
            LOG_ERROR("poll error err ! \n");
        }
    }
    return now;
}
void EpollPoller::updateChannel(Channel *channel)
{
    const int index = channel->index();
    LOG_INFO("fun:%s,fd:%d,events:%d,index:%d \n", __FUNCTION__, channel->fd(), channel->events(), index);
    if (index == Knew || index == Kdelete)
    {
        if (index == Knew)
        {
            int fd = channel->fd();
            channels_[fd] = channel;
        }
        channel->setindex(Kadded);
        update(EPOLL_CTL_ADD, channel);
    }
    else
    {
        int fd = channel->fd();
        if (channel->isNoneEvent())
        {
            update(EPOLL_CTL_DEL, channel);
            channel->setindex(Kdelete);
        }
        else
        {
            update(EPOLL_CTL_MOD, channel);
        }
    }
};
// 从poller中删除channel
void EpollPoller::removeChannel(Channel *channel)
{
    int fd = channel->fd();
    channels_.erase(fd);
    LOG_INFO("fun:%s,fd:%d", __FUNCTION__, channel->fd());

    int index = channel->index();

    if (index == Kadded)
    {
        update(EPOLL_CTL_DEL, channel);
    }
    channel->setindex(Knew);
};

// 填写活跃的链接
void EpollPoller::fillActiveChannel(int numEvents, ChannelList *activeChannels) const
{
    for (int i = 0; i < numEvents; i++)
    {
        Channel *channel = static_cast<Channel *>(events_[i].data.ptr);
        channel->set_events(events_[i].events); // 这里获取到活跃的并注册event
        activeChannels->push_back(channel);     // 得到活跃channel列表
    }
};
// 更新channel通道
void EpollPoller::update(int operation, Channel *channel)
{
    epoll_event event;
    memset(&event, 0, sizeof event);
    event.events = channel->events();
    event.data.ptr = channel;
    int fd = channel->fd();
    if (::epoll_ctl(epollfd_, operation, fd, &event) < 0)
    {
        if (operation == EPOLL_CTL_DEL)
        {
            LOG_ERROR("Epoll_ctl del error code%d", errno);
        }
        else
        {
            LOG_FATAL("Epoll_ctl del error code%d", errno);
        }
    }
};
